feat(wasm-utxo): redesign PSBT signing API for clarity and performance#116
Merged
OttoAllmendinger merged 2 commits intomasterfrom Jan 28, 2026
Merged
feat(wasm-utxo): redesign PSBT signing API for clarity and performance#116OttoAllmendinger merged 2 commits intomasterfrom
OttoAllmendinger merged 2 commits intomasterfrom
Conversation
Add a comprehensive benchmark for comparing bulk vs per-input signing performance across different script types (p2sh, p2shP2wsh, p2wsh, p2trLegacy, p2trMusig2KeyPath) with varying input counts. Co-authored-by: llm-git <llm-git@ttll.de>
Problem: The previous signing API had several issues: 1. `signInput(index, key)` claimed to sign only one input but actually signed ALL inputs internally (for ECDSA), which was misleading 2. MuSig2 bulk signing was inefficient - it recreated SighashCache for each input, recomputing sha_prevouts, sha_amounts, sha_scriptpubkeys, sha_sequences, and sha_outputs redundantly 3. The API didn't clearly communicate performance characteristics Solution: Implement an honest, clean WASM/Rust API that explicitly communicates what each method does and its performance implications. New WASM API (backward compatible - old methods kept as deprecated): - is_musig2_input(index) - check if input is MuSig2 keypath - sign_all_wallet_inputs(xpriv) - bulk sign ECDSA/Schnorr script path - sign_wallet_input(index, xpriv) - single input with save/restore (documented as NOT faster than bulk) - sign_musig2_input(index, xpriv) - single MuSig2 input - sign_all_musig2_inputs(xpriv) - NEW: bulk MuSig2 with SighashCache reuse for 2x performance improvement - sign_replay_protection_inputs(ecpair) - bulk replay protection TypeScript changes: - Added isBIP32Arg() type guard to js/bip32.ts - Updated sign(key) to call both sign_all_wallet_inputs and sign_all_musig2_inputs for optimal bulk performance - Updated signInput() to route to appropriate method based on input type Rust changes: - Added sign_with_first_round_and_cache() to Musig2Context that accepts external SighashCache and prevouts for efficient batch MuSig2 signing - Added corresponding wrapper in BitGoPsbt Performance results (1000 inputs): - ECDSA bulk: ~1.7ms per input (unchanged) - MuSig2 bulk: ~4.5ms per input (was ~9.5ms - 2x improvement!) The MuSig2 improvement comes from reusing SighashCache which caches the shared BIP-341 sighash components across all inputs. Issue: BTC-2980
a652454 to
e045dc5
Compare
davidkaplanbitgo
approved these changes
Jan 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR introduces a comprehensive redesign of the PSBT signing API to improve
clarity and performance, along with benchmarking tools to measure the impact.
Changes
performance implications
resulting in 2x performance improvement
types and input counts
New WASM API (backward compatible)
is_musig2_input(index)- Check if input is MuSig2 keypathsign_all_wallet_inputs(xpriv)- Bulk sign ECDSA/Schnorr script pathsign_wallet_input(index, xpriv)- Single input with save/restoresign_musig2_input(index, xpriv)- Single MuSig2 inputsign_all_musig2_inputs(xpriv)- Bulk MuSig2 with SighashCache reusesign_replay_protection_inputs(ecpair)- Bulk replay protectionPerformance Improvements
MuSig2 bulk signing now shows ~4.5ms per input (down from ~9.5ms),
representing a 2x improvement by reusing the SighashCache.
BTC-2980